<?php
class Chat{
    /**
     * 房间号参数转换(把chat_5或5统一转换成5)
     * @param $roomid string|int 房间号1 | chat_1
     * @return mixed
     */
    public static function getRoomID($roomid)
    {
        $pos = strpos($roomid, 'chat');
        if ($pos !== false){
            $roomid = str_replace('chat_', '', $roomid);
        }
        return $roomid;
    }
    // 取单个聊天室的参数
    public static function getRoomParas($roomid)
    {
        global $db;
        global $redis;
        global $utility;

        $roomid = self::getRoomID($roomid);
        $redis_key = \Config\Sys::$redisKey['CRLP'].$roomid;

        $data = $utility->redisGet($redis_key);
        if(!$data){
            $data = $db->row("SELECT * FROM `".\Config\Sys::$dbprefix."rooms` WHERE `id`=" . $roomid);
            $utility->redisSet($redis_key, $data);
        }
        return $data;
    }

    /**
     * 房间的黑名单列表
     * @param $roomid
     * @return mixed
     */
    public static function chatBlacklist($roomid)
    {
        global $db;
        global $redis;
        global $utility;

        $roomid = self::getRoomID($roomid);
        $redis_key = \Config\Sys::$redisKey['CRBL'].$roomid;

        $data = $utility->redisGet($redis_key);

        if(!$data){
            $data = $db->query("SELECT `uno` FROM `rp_rooms_blacklist` WHERE `roomid`=" . $roomid);
            $utility->redisSet($redis_key, $data);
        }
        return $data;
    }
    /**
     * 检测是否黑名单
     * @param $uno
     * @param $blacklist
     * @return bool
     */
    public static function existsBlackUser($uno, $blacklist)
    {
        $isBlackUser = false;
        if(is_array($blacklist)) {
            //$arr2 = array_column($blacklist, 'uno'); //php版本必须 >= 5.5.0
            foreach ($blacklist as $k => $v) {
                if (strval($v['uno']) === strval($uno)) {
                    $isBlackUser = true;
                    break;
                }
            }
        }
        return $isBlackUser;
    }
    public static function checkRoomType($paras)
    {
        global $db;
        global $redis;
        global $utility;
        $result = array('state'=>404, 'cmd'=>$paras['cmd']);
        $url_args = array(
            'cmd',
            'token',
            'nickname',
            'room_id',
        );
        $paras = $utility->get_url_args($paras, $url_args);

        //print_r($paras);

        $uno = '';
        if(empty($paras['room_id'])){
            $result['msgid'] = 10031;
            return $result;
            //return Gateway::sendToCurrentClient(json_encode($result));
        }
        $room_autoid = self::getRoomID($paras['room_id']);

        $data = $db->row("SELECT * FROM `".\Config\Sys::$dbprefix."rooms` WHERE `id`=".intval($room_autoid)." AND `state`=1");
        if(!$data)
        {
            $result['msgid'] = 10031;
            return $result;
            //return Gateway::sendToCurrentClient(json_encode($result));
        }
        $user = array(
            'uno' => 'S'.$utility->makeUserNo(),
            'usertype' => 0,
            'nickname' => '',
            'usercoin' => 0,
            'avatar' => 'no',
        );
        $user['nickname'] = empty($paras['nickname']) ? '游客S'.$user['uno'] : $paras['nickname'];
        $userToken['state'] = 404;
        if(!empty($paras['token'])) $userToken = $utility->exitsToKen($paras['token'],$paras['cmd']);

        if($userToken['state']==200){
            $user = $userToken;
        }
        if(intval($data['roomtype'])==1 && intval($user['usertype'])==0)
        {
            if($user['state']!=200)
            {
                $result['msgid'] = 10032;
                return $result;
            }
        }
        $uno = $user['uno'];
        # 拉取黑名单
        $isBlackUser = true;
        $blacklist = self::chatBlacklist($paras['room_id']);
        $isBlackUser = self::existsBlackUser($uno, $blacklist);
        if($isBlackUser){
            # 黑名单直接断开连接
            $result = array(
                'msgid' => 10035,
                'state' => 404,
                'cmd' => $paras['cmd'],
            );
            return $result;

        }
        //通知所有在房间的玩家
        //在线人数是当前总数+1，后面自己再加入
        $group_result = array(
            'cmd' => 'newuserjoin',
            'state' => 200,
            'nickname' =>  $user['nickname'],
            'useruno' => $user['uno'],
            'room_online' => 0,
            'time'=>$utility->formatTimes(time()),
        );
        unset($user['state']);
        unset($user['token']);
        $result = array(
            'state' =>200,
            'cmd' => $paras['cmd'],
            'roomid' => $paras['room_id'],
            'datas' => $data,
            'roomuser' => $user,
            'room_online' => 0,
            'room_userlist' => array(),
            'pushgroup' => $group_result,
        );
        return $result;
        //Gateway::sendToCurrentClient(json_encode($result));
    }
    /**
     * 生成当前游戏类型的期号
     * @param $chatid int 聊天室房号
     * @return string
     */
    public static function getChatRedIssue($chatid){
        global $db;
        global $redis;
        global $utility;

        $redis_key = \Config\Sys::$redisKey['CRISSUE'];
        $redis_key_date = \Config\Sys::$redisKey['CRISSUEDATA'];
        $issue_nums_len = 6;
        $issue_nums = 1000000; //要保留的期号长度,当前数字少一位数
        $nowdate = strval(date('Ymd'));
        # 如果Key存在且创建的日期是今天即从Redis缓存中取期数
        if($redis->exists($redis_key) && $nowdate==$redis->get($redis_key_date))
        {
            $redis_issue = $utility->redisGet($redis_key);
            $_issue = substr($redis_issue,-1,$issue_nums_len);
            $sourceNumber = intval($_issue) + 1;
            $newNumber = substr(strval($sourceNumber + $issue_nums), 1, 6);
        }else {
            $beginTimes = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
            $endTimes = $beginTimes + 86400;
            $sql = "SELECT (COUNT(1)+1) AS _TOTAL FROM `rp_rooms_red` WHERE `begintimes`>={$beginTimes} AND `begintimes`<={$endTimes} AND `chatid`={$chatid}";
            $issue_db = $db->row($sql);
            $sourceNumber = $issue_db['_TOTAL'];
            $newNumber = substr(strval($sourceNumber + $issue_nums), 1, 6);
        }
        $issue = date('Ymd') . $chatid . $newNumber;
        # 写入Redis
        $utility->redisSet($redis_key, $issue);
        return $issue;
    }
    /**
     * 所有可用的聊天室
     * @return mixed
     */
    public static function roomsList()
    {
        global $db;
        global $redis;
        global $utility;
        $redis_key = Config\Sys::$redisKey['CRAS'];

        $data = $utility->redisGet($redis_key);

        if(!$data){
            $fields = '`id`,`name`,`explain`,`icon`,`roomtype`';
            $tablename = Config\Sys::$dbprefix.'rooms';
            $where = 'state=1';
            $data = $db->select($fields)->from($tablename)->where($where)->query();
            $utility->redisSet($redis_key, $data);
        }

        $result['rooms'] = $data;
        $result['online'] = $redis->get(Config\Sys::$redisKey['ONLINES']);
        return $result;
    }

    public static function roomSay($paras)
    {
        global $db;
        global $redis;
        global $utility;

        $mastArgs = array('room_id','uno','nickname','avatar','to_uno','content','to_nickname','lastSayTimes','cmd','token');
        $paras = $utility->get_url_args($paras, $mastArgs);
        //print_r($paras);
        $result = array('state'=>404, 'saystate'=>404, 'cmd'=>$paras['cmd']);
        if(empty($paras['uno']))
        {
            $result['msgid'] = 301;
            return $result;
        }
        // 非法请求
        if(empty($paras['room_id']))
        {
            $result['msgid'] = 404;
            return $result;
        }
        $sayType = 'txt'; //默认是文字信息

        $say_content = nl2br(htmlspecialchars($paras['content']));
        $to_nickname = htmlspecialchars($paras['to_nickname']);
        //拉取黑名单
        $blacklist = self::chatBlacklist($paras['room_id']);
        $isBlackUser = self::existsBlackUser($paras['uno'], $blacklist);
        if($isBlackUser){
            //黑名单直接断开连接
            return json_encode(array(
                'state' => 200,
                'saystate' => 301, //黑名单
                'type' => 'txt',
                'content' => '你是本聊天室黑名单，请联系管理员解除！',
                'cmd' => $paras['cmd'],
                'from_uno'=>$paras['uno'],
                'from_nickname' =>$paras['nickname'],
                'to_uno'=>'',
                'to_nickname'=>'',
                'time'=>$utility->formatTimes(time()),
            ));
        }
        //拉取聊天室数据
        $roomdata = self::getRoomParas($paras['room_id']);
        //时间不能太快，默认5秒发一次言
        $nowtimes = time();
        if(isset($paras['lastSayTimes']))
        {
            if(($nowtimes - intval($paras['lastSayTimes'])) < $roomdata['interval'])
            {
                //太快了
                $result = array(
                    'state' => 200,
                    'saystate' => 302, //太快了
                    'cmd' => $paras['cmd'],
                    'from_uno'=>$paras['uno'],
                    'from_nickname' =>$paras['nickname'],
                    'from_avatar' => $paras['avatar'],
                    'to_uno'=>'',
                    'to_nickname'=>'',
                    'type'=>$sayType,
                    'content'=>"你的发言速度过快，请间隔".$roomdata['interval']."秒后再发！",
                    'time'=>$utility->formatTimes($nowtimes),
                );
                return $result;
            }
        }
        $isAdmins = strpos($roomdata['admins'], $paras['uno'].',');
        if(intval($roomdata['nosay'])==1 && $isAdmins===false)
        {
            $result = array(
                'state' => 200,
                'saystate' => 303, //禁言状态
                'cmd' => $paras['cmd'],
                'from_uno' => $paras['uno'],
                'from_nickname' => $paras['nickname'],
                'from_avatar' => $paras['avatar'],
                'to_uno' => '',
                'to_nickname'=>'',
                'type' => $sayType,
                'content' => "系统提示：当前为禁言状态，请稍后再试！",
                'time'=>$utility->formatTimes($nowtimes),
            );
            return $result;
        }
        // 私聊
        if($paras['to_uno'] != 'all')
        {
            $result = array(
                'state'=>200,
                'saystate' => 304, // 私聊
                'cmd'=>$paras['cmd'],
                'from_uno'=>$paras['uno'],
                'from_nickname' =>$paras['nickname'],
                'from_avatar' => $paras['avatar'],
                'to_uno'=>$paras['to_uno'],
                'to_nickname'=>$paras['to_nickname'],
                'type'=>$sayType,
                'content'=>"<pb>私</pb>".$say_content,
                'time'=>$utility->formatTimes($nowtimes),
            );
            //$result['content'] = "<pb>私</pb>".$say_content;
            //Gateway::sendToUid($paras['to_uno'], json_encode($result));
            return $result;
        }
        $result = array(
            'state'=>200,
            'saystate' => 200,
            'cmd'=>'say',
            'from_uno'=>$paras['uno'],
            'from_nickname' =>$paras['nickname'],
            'from_avatar' => $paras['avatar'],
            'to_uno'=>'all',
            'type'=>$sayType,
            'content'=>$say_content,
            'time'=> $utility->formatTimes($nowtimes),
        );
        //如果要记录数据库的
        if($roomdata['savedb']==1)
        {
            $chatlog = array(
                'roomid' => $roomdata['id'],
                'from_uno'=>$paras['uno'],
                'from_nickname' => $paras['nickname'],
                'from_avatar' => $paras['avatar'],
                'to_uno' =>$paras['to_uno'],
                'content'=>$say_content,
                'chattype'=>$sayType,
                'state'=>1,
                'times'=>$nowtimes,
            );
            $db->insert('rp_rooms_chatlog')->cols($chatlog)->query();
        }
        //记录最后发言的时间
        $paras['lastSayTimes'] = time();
        return $result;
    }

    /**
     * 发红包
     * @param $paras
     * @return array
     */
    public static function sendRedEnvelopes($paras)
    {
        global $db;
        global $redis;
        global $utility;

        $db_prefix = Config\Sys::$dbprefix;


        # 要检测的URL参数
        # coin float 红包金额
        # nums int 红包数量
        # room_id string 聊天室房间号码，chat_1或1
        # token string 聊天室用户token
        # remoteip string 用户远程IP
        $mastArgs = array('coin|F', 'nums|N', 'room_id', 'token','remoteip','cmd');
        $paras = $utility->get_url_args($paras, $mastArgs);

        $result = array('state'=>404,'cmd'=>$paras['cmd']);

        $coin = $paras['coin'];
        $nums = $paras['nums'];
        $room_id = $paras['room_id'];

        if($coin < 0.02){
            $result['msgid'] = 10036;
            return $result;
        }
        if($nums < 2){
            $result['msgid'] = 10037;
            return $result;
        }
        if(empty($room_id)){
            $result['msgid'] = 404;
            return $result;
        }
        $userToken = $utility->exitsToKen($paras['token'],$paras['cmd']);

        if($userToken['state']==200){
            // 试玩用户不能发送聊天室红包
            if($userToken['usertype']==0){
                return array(
                    'state' => 404,
                    'msgid' => 10085,
                );
            }

            # 需要扣除注册赠送的金额，注册赠送的金额不能在聊天室发送红包，只能用来玩游戏
            $sql = 'SELECT IFNULL(SUM(coin),0) AS _TOTAL FROM `'.\Config\Sys::$dbprefix.'givecoinlog` WHERE `uid`='.$userToken['uid'].' AND `liqtype` IN(23,25)';
            $givecoin = $db->row($sql);
            $givecoin = $givecoin['_TOTAL'];
            $userToken['usercoin'] = $userToken['usercoin'] - $givecoin;
            if($userToken['usercoin'] < ($coin)){
                $result['msgid'] = 10005;
                return $result;
            }

            $nowtimes = time();
            # 发包的期号
            $roomnid = self::getRoomID($room_id);
            $issue = self::getChatRedIssue($roomnid);
            $issue = 'C' . $issue;
            $db->beginTrans();
                # 添加发包记录
                $send_log = array(
                    'issue' => $issue,
                    'uid' => $userToken['uid'],
                    'nums' => $nums,
                    'cur' => 0,
                    'coin' => $coin,
                    'freecoin' => $coin,
                    'ip' => $paras['remoteip'],
                    'begintimes' => $nowtimes,
                    'chatid' => $roomnid,
                );
                $insertId = $db->insert($db_prefix.'rooms_red')->cols($send_log)->query();
                # 记发红包的帐变
                $utility->setCoin(
                    array(
                        'uid' => $userToken['uid'],
                        'coin' => (0-floatval($coin)),
                        'liqtype' => 17, // 聊天室发红包
                        'ex1' => $insertId,
                        'ex2' => $issue,
                    )
                );
            $db->commitTrans();
            // 记录到Redis缓存中
            $redis_key_issue = \Config\Sys::$redisKey['CRISSUE'] . $issue;
            //$this->utility->redisSet($this->redis, $redis_key_issue, $issue);
            $redis->rpush($redis_key_issue, $userToken['uno']); // 把自己加入到队列中

            # 生成红包
            $red_log = $utility->redPacketRound($coin, $nums);
            # 记录到Redis中
            $redis_key_issue = \Config\Sys::$redisKey['CRISSUE'] . $issue . '_coinlist';
            foreach ($red_log as $key=>$val) {
                $redis->sadd($redis_key_issue, strval($val['coin']));
            }
            # 记录到数据库
            /*
            $insert_sql = "INSERT INTO `rp_rooms_red_log` (`redid`,`issue`,`coin`) VALUES";
            $insert_sql_value = "";
            foreach ($red_log as $key=>$val)
            {
                $insert_sql_value .= "(".$insertId.",'".$issue."',".$val['coin'].")";
            }
            */
            //自己发的红包自己也可以抢
            # 发送给前端显示
            $result = array(
                'state'=>200,
                'cmd'=>'say',
                'room_id' => $room_id,
                'from_uno'=>$userToken['uno'],
                'from_nickname' =>$userToken['nickname'],
                'from_avatar' => $userToken['avatar'],
                'to_uno'=>'all',
                'type'=>'hb',
                'issue'=>$issue,
                'time'=> $utility->formatTimes($nowtimes),
                'overtimes' => 180,
                'usercoin' => $utility->formatCoin($userToken['usercoin'] - $coin),
            );
            return $result;
        }else{
            $result['state'] = $userToken['state'];
            $result['msgid'] = $userToken['msgid'];
            return $result;
        }
    }

    /**
     * 抢红包
     * @param $paras
     * @return array
     */
    public static function gradRedEnvelopes($paras)
    {
        global $db;
        global $redis;
        global $utility;

        $db_prefix = Config\Sys::$dbprefix;

        # 要检测的URL参数
        # coin float 红包金额
        # nums int 红包数量
        # room_id string 聊天室房间号码，chat_1或1
        # token string 聊天室用户token
        # remoteip string 用户远程IP
        $mastArgs = array('issue', 'room_id', 'remoteip','cmd','token');
        $paras = $utility->get_url_args($paras, $mastArgs);

        $result = array('state' => 404,'cmd'=>$paras['cmd']);
        if(empty($paras['issue']))
        {
            $result['state'] = 404;
            $result['msgid'] = 10020;
            return $result;
        }
        if(empty($paras['room_id']))
        {
            $result['state'] = 404;
            $result['msgid'] = 10021; // 聊天室号码错误
            return $result;
        }

        $userToken = $utility->exitsToKen($paras['token'],$paras['cmd']);

        //记录当前时间
        $nowtime = time();
        $paras['nowtime'] = $nowtime;
        $redis_key_issue = Config\Sys::$redisKey['CRISSUE'] . $paras['issue'];

        if($userToken['state']==200){
            // 试玩用户不能参与聊天室红包
            if($userToken['usertype']==0){
                return array(
                    'state' => 404,
                    'msgid' => 10085,
                );
            }

            $uid = $userToken['uid'];
            //如果Redis中没有了以当期红包期数为Key创建的列表即红包为无效
            if(!$redis->exists($redis_key_issue)){
                $result['state'] = 404;
                $result['msgid'] = 10016;
                return $result;
            }
            //要在Redis中查找这个UNO是否存在于列表中，如果有就不能再参与了
            $isHaveNuo = $utility->existsRedisKey($redis_key_issue, $userToken['uno']);
            # 当列表中存在这个UNO时直接组织展示数据给前台
            if ($isHaveNuo) {
                $result['state'] = 404;
                $result['msgid'] = 10017; // 红包不能重复抢
                return $result;
            }

            //找出当前期数的红包
            $red_data = $db->row("SELECT * FROM `".\Config\Sys::$dbprefix."rooms_red` WHERE `issue`='{$paras['issue']}' AND `state`=0");
            if(!$red_data){
                $result['state'] = 404;
                $result['msgid'] = 10016;
                return $result;
            }

            //自己发的红包不能自己去抢

            //*/
            //统计当前期数的人数(要在Redis中统计参与人数) - 1 是因为创建的时候把自己加入了列表，自动不能抢，
            //为了创建一个KEY来为后面的作识别
            $_total = $redis->llen($redis_key_issue) - 1;

            if($red_data['nums'] <= $_total){
                //人数已够，抢包失败
                $result['state'] = 404;
                $result['msgid'] = 10015;
                return $result;
            }
            $paras['curusernum'] = $_total;

            //加到Redis队列中
            $redis->rpush($redis_key_issue, $userToken['uno']);

            # 从LIST中随机抽取一个红包
            $redis_key_issue = \Config\Sys::$redisKey['CRISSUE'] . $paras['issue'] . '_coinlist';
            # 随机从列队中抽取一个并删除这个值
            $_redcoin = $redis->spop($redis_key_issue);
            # 记录抽中的红包
            # $insert_sql = "INSERT INTO `rp_rooms_red_log` (`redid`) VALUES ()";
            # 记帐变

            if($_redcoin)
            {
                $db->beginTrans();
                $utility->setCoin(
                    array(
                        'uid' => $userToken['uid'],
                        'coin' => floatval($_redcoin), //帐变扣款是负数，返回时须用0去减变回正数
                        'gameid' => self::getRoomID($paras['room_id']),
                        'liqtype' => 18, // 聊天室抢到的红包
                        'ex1' => $red_data['id'],
                        'ex2' => $paras['issue'],
                    )
                );
                # 更新到发包记录
                $db->query("UPDATE `rp_rooms_red` SET `freecoin` = `freecoin` - ".$_redcoin." WHERE `issue`='".$paras['issue']."' LIMIT 1");
                $db->commitTrans();

                $result = array(
                    'state' => 200,
                    'cmd' => $paras['cmd'],
                    'room_id' => $paras['room_id'],
                    'issue' => $paras['issue'],
                    'coin' => $_redcoin,
                    'usercoin' => $utility->formatCoin($userToken['usercoin'] + $_redcoin),
                );

                # 组装推送给组员的玩家抢红包记录
                $result['groupmsg'] = array(
                    'cmd' => 'newusergrab',
                    'issue' => $paras['issue'],
                    'coin' => $_redcoin,
                    'nickname' => $userToken['nickname'],
                );

                if($redis->llen($redis_key_issue) >= $red_data['nums'])
                {
                    $redis->delete($redis_key_issue);
                }
            }else{
                //红包金额已分配完毕，抢包失败
                $result['state'] = 404;
                $result['msgid'] = 10015;
                return $result;
            }

        }else{
            $result['state'] = $userToken['state'];
            $result['msgid'] = $userToken['msgid'];
        }
        return $result;
    }
}